package mythread;

/**
 * @Auther: cty
 * @Date: 2020/1/7 13:50
 * @Description: 线程同步——块同步(double checking 临界值问题)
 * @version: 1.0
 */
public class Hf_SynBlockTest1_2 implements Runnable{
    private int ticketsNum = 99;  //剩余车票数
    private boolean flag = true;

    @Override
    public void run() {
        while(flag){
            //模拟网络延迟
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            test();
        }
    }

    void test(){
        if (ticketsNum <= 0) {  //考虑票为0的情况，线程直接退出，不需要等待资源，【提高效率】
            flag = false;
            return;
        }
        synchronized (this) {  //已经能够满足线程安全问题，但效率低下
            //假如ticketsNum=0，1线程进入，2线程和3线程就要等待，1线程进入后发现ticketsNum=0，1线程把flag置为false（1线程进入的作用）
            // 2线程和3线程再分别进入，发现ticketsNum=0后退出。可以看到1线程进入是有用的，但2、3线程却白白浪费了等待时间
            if (ticketsNum <= 0) {  //考虑票为1的情况
                flag = false;
                return;
            }
            //模拟网络延迟
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"售出了 "+ticketsNum--+" 号票,剩余 "+ticketsNum+"张票");  //【打印】和【修改】
        }
    }

    public static void main(String[] args) {
        //一份任务
        Hf_SynBlockTest1_2 ticket = new Hf_SynBlockTest1_2();
        //多个代理
        new Thread(ticket,"窗口1").start();  //第一个new Thread开辟工作空间，其他代理线程共享工作空间中的资源
        new Thread(ticket,"窗口2").start();
        new Thread(ticket,"窗口3").start();
    }
}
